package android.eventfinder;

import java.io.BufferedInputStream;
import java.io.InputStream;
import java.io.StringReader;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.apache.http.util.ByteArrayBuffer;
import org.w3c.dom.CharacterData;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;

import android.app.Activity;
import android.app.TabActivity;
import android.content.Context;
import android.content.Intent;
import android.graphics.drawable.Drawable;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.location.LocationProvider;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.DatePicker;
import android.widget.EditText;

public class Search extends Activity implements OnClickListener {
	/** Called when the activity is first created. */

	EditText text = null;
	EditText tags = null;
	Button btn = null;
	DatePicker dPicker = null;
	
	private int mYear;
	private int mMonth;
	private int mDay;
	private Calendar calendar;
	// current location (the center of the map)
	private double longitude = -93.26384;
	private double latitude = 44.97997;
	private Location location = null;
	LocationManager locationManager;
	LocationListener locationListener;

	public void onCreate(Bundle savedInstanceState) {

		super.onCreate(savedInstanceState);
		setContentView(R.layout.search);
		text = (EditText) findViewById(R.id.edit_text);
		tags = (EditText) findViewById(R.id.edit_text2);
		btn = (Button) findViewById(R.id.button);
		dPicker = (DatePicker) findViewById(R.id.dPicker);
		calendar = Calendar.getInstance();

		mYear = calendar.get(Calendar.YEAR);
		mMonth = calendar.get(Calendar.MONTH);
		mDay = calendar.get(Calendar.DAY_OF_MONTH) + 3;
		dPicker.init(mYear, mMonth, mDay,
				new DatePicker.OnDateChangedListener() {
					@Override
					public void onDateChanged(DatePicker view, int year,
							int monthOfYear, int dayOfMonth) {
						mYear = year;
						mMonth = monthOfYear;
						mDay = dayOfMonth;

					}

				});
		btn.setOnClickListener(this);

		// --------------------------- Use GPS
		// --------------------------------------
		locationManager = (LocationManager) this
				.getSystemService(Context.LOCATION_SERVICE);

		locationListener = new LocationListener() {
			public void onLocationChanged(Location changedLocation) {
				location = changedLocation;
				longitude = location.getLongitude();
				latitude = location.getLatitude();
			}

			public void onProviderDisabled(String provider) {
			}

			public void onProviderEnabled(String provider) {
			}

			public void onStatusChanged(String provider, int status,
					Bundle extras) {
			}
		};
		locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0,
				0, locationListener);
		
		//if (text.getText().toString().equals("")) // if the user don't type city
													// name, use GPS to get
													// location
		//location = locationManager.getLastKnownLocation(Context.LOCATION_SERVICE);
		// ------------------------------------------------------------
	}

	public static String getCharacterDataFromElement(Element e) {
		Node child = e.getFirstChild();
		if (child instanceof CharacterData) {
			CharacterData cd = (CharacterData) child;
			return cd.getData();
		}
		return "?";
	}

	public static ArrayList<Venue> getDataFromXML(double latitude,
			double longitude, int lengthOfText, String cityName, Date maxDate, String tags) {
		/* Will be filled and displayed later. */
		String myString = null;

		// Stores the venues to return
		ArrayList<Venue> venueList = new ArrayList<Venue>();

		try {
			// If city is from GPS, then use lat & long in URL
			/* Define the URL we want to load data from. */
			URL myURL;

			if (lengthOfText == 0) {
				myURL = new URL(
						"http://ws.audioscrobbler.com/2.0/?method=geo.getevents&lat="
								+ Double.toString(latitude)
								+ "&long="
								+ Double.toString(longitude)
								+ "&api_key=b25b959554ed76058ac220b7b2e0a026&limit=50");
			} else {
				cityName = cityName.replaceAll(" ", "+");
				myURL = new URL(

				"http://ws.audioscrobbler.com/2.0/?method=geo.getevents&location="
						+ cityName
						+ "&api_key=b25b959554ed76058ac220b7b2e0a026&limit=50");
			}
			/* Open a connection to that URL. */
			URLConnection ucon = myURL.openConnection();

			/*
			 * Define InputStreams to read from the URLConnection.
			 */
			InputStream is = ucon.getInputStream();
			BufferedInputStream bis = new BufferedInputStream(is);

			/*
			 * Read bytes to the Buffer until there is nothing more to read(-1).
			 */
			ByteArrayBuffer baf = new ByteArrayBuffer(50);
			int current = 0;
			while ((current = bis.read()) != -1) {
				baf.append((byte) current);
			}

			/* Convert the Bytes read to a String. */
			myString = new String(baf.toByteArray());
		} catch (Exception e) {
			/* On any Error we want to display it. */
			myString = e.getMessage();
		}

		// Convert string to arrays of events
		try {
			

			DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
			DocumentBuilder db = dbf.newDocumentBuilder();
			InputSource is = new InputSource();
			is.setCharacterStream(new StringReader(myString));

			Document doc = db.parse(is);
			NodeList nodes = doc.getElementsByTagName("event");

			// iterate the events
			for (int i = 0; i < nodes.getLength(); i++) {
				Element element = (Element) nodes.item(i);

				// Get event information

				// Title of Event
				NodeList title = element.getElementsByTagName("title");
				Element line = (Element) title.item(0);
				String theTitle = getCharacterDataFromElement(line);

				// Date of Event
				NodeList date = element.getElementsByTagName("startDate");
				line = (Element) date.item(0);
				String theDate = getCharacterDataFromElement(line);
				Date eventDate = new Date(theDate);
				// Have to pull out the year manually
				eventDate.setYear(Integer.parseInt(theDate.substring(12, 16))); 


				// Name of Headliner
				NodeList headliner = element.getElementsByTagName("headliner");
				line = (Element) headliner.item(0);
				String theHeadliner = getCharacterDataFromElement(line);

				// Name of Venue
				NodeList venue = element.getElementsByTagName("name");
				line = (Element) venue.item(0);
				String theVenue = getCharacterDataFromElement(line);
				
				// Street of Venue
				NodeList street = element.getElementsByTagName("street");
				line = (Element) street.item(0);
				String theStreet = getCharacterDataFromElement(line);
				
				// City of Venue
				NodeList city = element.getElementsByTagName("city");
				line = (Element) city.item(0);
				String theCity = getCharacterDataFromElement(line);

				// Zip of Venue
				NodeList postalcode = element.getElementsByTagName("postalcode");
				line = (Element) postalcode.item(0);
				String theZip = getCharacterDataFromElement(line);
				
				// List of Tags
				ArrayList<String> eventTags = new ArrayList<String>();
				NodeList tag = element.getElementsByTagName("tag");
				for (int j = 1; j < tag.getLength(); j++) {
					line = (Element) tag.item(j);
					eventTags.add(getCharacterDataFromElement(line));
				}

				// Geo location
				NodeList venueLat = element.getElementsByTagName("geo:lat");
				line = (Element) venueLat.item(0);
				double theVenueLat = Double
						.parseDouble(getCharacterDataFromElement(line));
				NodeList venueLong = element.getElementsByTagName("geo:long");
				line = (Element) venueLong.item(0);
				double theVenueLong = Double
						.parseDouble(getCharacterDataFromElement(line));
				MyLocation theVenueLoc = new MyLocation(theVenueLat,
						theVenueLong);
				
				// Get tags to compare from input sting;
				
				String tagArray[] = tags.split(",");
				
				// maxDate begins at midnight (00:00), so to make sure you include this day, set the
				// hours and minutes to (23:59)
				maxDate.setHours(23);
				maxDate.setMinutes(59);
				// If the date is out of range, do not add it to the results
				if (!maxDate.before(eventDate)) {
					boolean addToArray = true;
					// Check tags to filter results
					boolean tagFound = false;
					for(int j = 0; j < tagArray.length; j++) {
						tagFound = false;
						for(int k = 0; k < eventTags.size(); k++) {
							
							if(eventTags.get(k).contains(tagArray[j])) {
								tagFound = true;
							}
							
							
						}
						if(tagFound == false) {
							addToArray = false;
							break;
						}
					}
					
					// If the tag was found, add event to array
					if (addToArray) {
						
					// Add event info to new Event
					Event eventToAdd = new Event(eventDate, theTitle);
					eventToAdd.setArtist(theHeadliner);
					eventToAdd.setTags(eventTags);

					// Create Venue if not already created
					int indexOfVenue = -1;
					for (int j = 0; j < venueList.size(); j++) {
						if (venueList.get(j).getName().compareTo(theVenue) == 0) {
							indexOfVenue = j;
						}
					}

					// if venue found, then add to that venue
					if (indexOfVenue >= 0) {
						venueList.get(indexOfVenue).addEvent(eventToAdd);
					}
					// Or else create the venue
					else {
						Venue venueToAdd = new Venue(theVenue, theVenueLoc, theStreet, theCity, theZip);
						venueToAdd.addEvent(eventToAdd);
						venueList.add(venueToAdd);
					}
					}
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}

		return venueList;
	}

	@Override
	public void onClick(View v) { // click button
		
		if (text.getText().toString().length() == 0) {
			// The user isn't going to change location, so we can stop the location listener when they have clicked the button
			String locationProvider = LocationManager.GPS_PROVIDER;
			// Or use LocationManager.GPS_PROVIDER

			Location lastKnownLocation = locationManager.getLastKnownLocation(locationProvider);
			location = lastKnownLocation;
		}
		
		locationManager.removeUpdates(locationListener);
		
		if (location != null) {
			latitude = location.getLatitude();
			longitude = location.getLongitude();
		}
		Date maxDate = new Date(mYear, mMonth, mDay);
		int lengthOfText = text.getText().length();
		ArrayList<Venue> retVenues = getDataFromXML(latitude, longitude,
				lengthOfText, text.getText().toString(), maxDate, tags.getText().toString());

		if (lengthOfText != 0 && retVenues.size() > 0) { // location is gotten
															// from first venue
			// Update location to move map
			latitude = retVenues.get(0).getLocation().latitude;
			longitude = retVenues.get(0).getLocation().longitude;
			
		}

		MyLocation newLocation = new MyLocation(latitude, longitude);

		// save data to GlobalState
		GlobalState gs = (GlobalState) getApplication();
		ArrayList<Venue> venues = gs.getData();
		gs.setLocation(newLocation);
		venues.clear();
		for (int i = 0; i < retVenues.size(); i++) {
			venues.add(retVenues.get(i));
		}

		// call Map activity
		Intent intent = new Intent(this, Map.class);
		startActivity(intent);
	}

}